package com.zyj.core.executor;

import com.zyj.core.config.Configuration;
import com.zyj.core.config.MappedStatement;
import com.zyj.core.handler.statementhandler.StatementHandler;
import com.zyj.core.sqlsource.BoundSql;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 * 默认的执行器，是真正的执行器
 */
public class SimpleExecutor extends BaseExecutor {

    /**
     * 真正查询数据库的方法
     *
     * @param configuration
     * @param mappedStatement
     * @param boundSql        其中封装了sql与参数映射关系【参数名称及对应的参数类型】
     * @param param           如果是多个参数，则是map类型，如果是单个参数，则是简单类型，其中保存了参数名称和参数值
     *                        Map map = new HashMap();
     *                        map.put("username", "千年老亚瑟");
     *                        map.put("sex", "男");
     * @param <T>
     * @return
     */
    @Override
    protected <T> List<T> queryFromDataBase(Configuration configuration, MappedStatement mappedStatement, BoundSql boundSql, Object param) {

        // 数据库连接对象
        Connection connection = null;
        // statement对象
        Statement statement = null;
        // 结果集对象
        ResultSet rs = null;

        // 存储ResultSet解析之后的结果集
        List<T> results = new ArrayList<>();

        try {
            // 根据数据库配置信息从数据源获取连接
            connection = getConnection(configuration);

            /**
             * 根据mappedStatement中封装好的statementType类型，获取StatementHandler
             */
            // 根据传入的statementType获取对应的StatementHandler类型
            // 默认返回PreparedStatementHandler
            StatementHandler statementHandler = configuration.newStatementHandler(mappedStatement.getStatementType());

            /**
             * 由statementHandler来
             * 1.获取预编译statement
             * 2.处理参数
             * 3.执行查询并且处理结果集
             */
            // 获取StatementType,创建Statement
            statement = statementHandler.prepare(connection, boundSql.getSql());
            // 设置参数
            statementHandler.parameterize(statement, param, boundSql);
            // 执行Statement查询，并且处理结果集
            results = statementHandler.query(statement, mappedStatement);

            // 返回处理结束的结果映射
            return results;

        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            // 8、释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    /**
     * 根据配置文件中的数据库配置信息获取数据库连接
     *
     * @param configuration
     * @return
     * @throws Exception
     */
    private Connection getConnection(Configuration configuration) throws Exception {
        // 从configuration对象中取出封装好的数据库信息
        DataSource dataSource = configuration.getDataSource();
        // 根据dataSource获取连接
        return dataSource.getConnection();
    }
}
